#include <stdio.h>

typedef enum {
    S_RUN = 0,
    S_BLOCK,
    S_READY,
    S_DEAD,
    S_MAX,
} state_t;

typedef enum {
    E_IO = 0,
    E_WAKEUP,
    E_SCHED,
    E_KILL,
    E_MAX,
} event_t;

typedef struct {
    int id;
} param_t;

typedef void* (*action_ptr)(param_t *param);

typedef struct {
  action_ptr action;
  state_t    next_state;
} sm_t;

static inline void *dead (param_t *param)
{
    printf("=> normal dead\n");
}

static inline void *error (param_t *param)
{
    printf("=> abnormal dead\n");
}

static inline void *block (param_t *param)
{
    printf("=> block ");
}

static inline void *ready (param_t *param)
{
    printf("=> ready ");
}

static inline void *run (param_t *param)
{
    printf("=> run ");
}

/*
 * The state machine translation table
 * |--------+-------+-------+-------|
 * | event  | RUN   | BLOCK | READY |
 * |--------+-------+-------+-------|
 * | IO     | block | dead  | dead  |
 * | WAKEUP | dead  | ready | dead  |
 * | SCHED  | dead  | dead  | run   |
 * | KILL   | dead  | dead  | dead  |
 * |--------+-------+-------+-------|
 */
sm_t sm_table[E_MAX][S_MAX] = {
    {{block, S_BLOCK}, {error, S_DEAD}, {error, S_DEAD}},
    {{error, S_DEAD}, {ready, S_READY}, {error, S_DEAD}},
    {{error, S_DEAD}, {error, S_DEAD}, {run, S_RUN}},
    {{dead, S_DEAD}, {dead, S_DEAD}, {dead, S_DEAD}},
};

int get_event (int *event)
{
    char c;
    char ops[5] = {'i', 'w', 's', 'i', 'k'};
    static int step = 0;
    
    char map[256] = { -1 };
    map['i'] = E_IO;
    map['w'] = E_WAKEUP;
    map['s'] = E_SCHED;
    map['k'] = E_KILL;

    /* c = fgetc(stdin); */
    c = ops[step];
    step++;
    step %= 5;
    *event = map[c];

    return (c != -1);
}

int main(int argc, char *argv[])
{
    int event = 0;
    state_t cur_state = S_RUN;
    param_t param;
    
    while (cur_state != S_DEAD) {
        if (get_event(&event)) {
            sm_table[event][cur_state].action(&param);
            cur_state = sm_table[event][cur_state].next_state;
        }
    }
    return 0;
}

